/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import GUI.Helper;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 *
 * @author TrongKhoa
 */
public class XmlHelper
{

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException
    {
        Document doc = CreateDocument("ROOT");
        Element x = doc.createElement("Name");
        x.setAttribute("XXX", "YYY");

        doc.getDocumentElement().appendChild(x);

        Text y = doc.createTextNode("YYY");
        x.appendChild(y);
        Element z = doc.createElement("NEWELE");
        z.setTextContent("HEHE");
        x.appendChild(z);



        //Node z = doc.createTextNode("ZZZ");
        //y.appendChild(z);
        //x.appendChild(y);


//                Parse("D:/data.xml");
        System.out.println(writeXmlToFile("E:/abc.xml", doc));
    }

    public static Document CreateDocument(String rootName)
    {
        Document doc = null;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try
        {
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder.newDocument();
            Element rootElement = doc.createElement(rootName);
            doc.appendChild(rootElement);
        }
        catch (Exception e)
        {
            Helper.Print("Lỗi không tạo được New Document!");
        }

        return doc;
    }

    public static Document Parse(String fileName) throws SAXException, IOException
    {
        Document document = null;
        // Initiate DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // To get a validating parser
        factory.setValidating(false);
        // To get one that understands namespaces
        factory.setNamespaceAware(true);

        try
        {
            // Get DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();
            // Parse and load into memory the Document
            document = builder.parse(new File(fileName));
            return document;

        }
        catch (SAXParseException spe)
        {
            // Error generated by the parser
            System.out.println("\n** Parsing error , line " + spe.getLineNumber()
                    + ", uri " + spe.getSystemId());
            System.out.println(" " + spe.getMessage());
            // Use the contained exception, if any
            Exception x = spe;
            if (spe.getException() != null)
            {
                x = spe.getException();
            }
            x.printStackTrace();
        }
        catch (SAXException sxe)
        {
            // Error generated during parsing
            Exception x = sxe;
            if (sxe.getException() != null)
            {
                x = sxe.getException();
            }
            x.printStackTrace();
        }
        catch (ParserConfigurationException pce)
        {
            // Parser with specified options can't be built
            pce.printStackTrace();
        }
        catch (IOException ioe)
        {
            // I/O error
            ioe.printStackTrace();
        }

        return null;
    }

    /**
     * Prints the specified node, then prints all of its children.
     */
    public static void printDOM(Node node)
    {
        int type = node.getNodeType();
        switch (type)
        {
            // print the document element
            case Node.DOCUMENT_NODE:
            {
                System.out.println("<?xml version=\"1.0\" ?>");
                printDOM(((Document) node).getDocumentElement());
                break;
            }

            // print element with attributes
            case Node.ELEMENT_NODE:
            {
                System.out.print("<");
                System.out.print(node.getNodeName());
                NamedNodeMap attrs = node.getAttributes();
                for (int i = 0; i < attrs.getLength(); i++)
                {
                    Node attr = attrs.item(i);
                    System.out.print(" " + attr.getNodeName().trim()
                            + "=\"" + attr.getNodeValue().trim()
                            + "\"");
                }
                System.out.println(">");

                NodeList children = node.getChildNodes();
                if (children != null)
                {
                    int len = children.getLength();
                    for (int i = 0; i < len; i++)
                    {
                        printDOM(children.item(i));
                    }
                }

                break;
            }

            // handle entity reference nodes
            case Node.ENTITY_REFERENCE_NODE:
            {
                System.out.print("&");
                System.out.print(node.getNodeName().trim());
                System.out.print(";");
                break;
            }

            // print cdata sections
            case Node.CDATA_SECTION_NODE:
            {
                System.out.print("<![CDATA[");
                System.out.print(node.getNodeValue().trim());
                System.out.print("]]>");
                break;
            }

            // print text
            case Node.TEXT_NODE:
            {
                System.out.print(node.getNodeValue().trim());
                break;
            }

            // print processing instruction
            case Node.PROCESSING_INSTRUCTION_NODE:
            {
                System.out.print("<?");
                System.out.print(node.getNodeName().trim());
                String data = node.getNodeValue().trim();
                {
                    System.out.print(" ");
                    System.out.print(data);
                }
                System.out.print("?>");
                break;
            }
        }

        if (type == Node.ELEMENT_NODE)
        {
            System.out.println();
            System.out.print("</");
            System.out.print(node.getNodeName().trim());
            System.out.print('>');
        }
    }

    /**
     * This method writes a DOM document to a file
     *
     * @param filename
     * @param document
     */
    public static String writeXmlToFile(String filename, Document document)
    {
        try
        {
            // Prepare the DOM document for writing
            Source source = new DOMSource(document);

            // Prepare the output file
            File file = new File(filename);
            Result result = new StreamResult(file);

            // Write the DOM document to the file
            // Get Transformer
            TransformerFactory tfFactory = TransformerFactory.newInstance();

            Transformer transformer = tfFactory.newTransformer();

            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            // Write to a file
            transformer.transform(source, result);

            //For debug
            StringWriter stringWriter = new StringWriter();
            StreamResult xmlOutput = new StreamResult(stringWriter);
            transformer.transform(source, xmlOutput);
            return xmlOutput.getWriter().toString();

        }
        catch (TransformerConfigurationException e)
        {
            System.out.println("TransformerConfigurationException: " + e);
        }
        catch (TransformerException e)
        {
            System.out.println("TransformerException: " + e);
        }
        return "";
    }

    /**
     * Count Elements in Document by Tag Name
     *
     * @param tag
     * @param document
     * @return number elements by Tag Name
     */
    public static int countByTagName(String tag, Document document)
    {
        NodeList list = document.getElementsByTagName(tag);
        return list.getLength();
    }

    public static int GetIntNodeValueByXPath(String xpathStr, Document doc) throws XPathExpressionException
    {
        XPathFactory xpFac = XPathFactory.newInstance();
        XPath xpath = xpFac.newXPath();
        return Integer.parseInt(xpath.evaluate(xpathStr, doc));
    }

    public static NodeList GetNodeListByXPath(String xpathStr, Document doc) throws XPathExpressionException
    {
        XPathFactory xpFac = XPathFactory.newInstance();
        XPath xpath = xpFac.newXPath();
        return (NodeList) xpath.evaluate(xpathStr, doc, XPathConstants.NODESET);
    }

    public static Node GetNodeByXPath(String xpathStr, Document doc) throws XPathExpressionException
    {
        XPathFactory xpFac = XPathFactory.newInstance();
        XPath xpath = xpFac.newXPath();
        return (Node) xpath.evaluate(xpathStr, doc, XPathConstants.NODE);
    }

    public static Number GetFucntionResultByXPath(String xpathStr, Document doc) throws XPathExpressionException
    {
        XPathFactory xpFac = XPathFactory.newInstance();
        XPath xpath = xpFac.newXPath();
        return ((Number) xpath.evaluate(xpathStr, doc, XPathConstants.NUMBER));
    }
}
